iT邦幫忙

2022 iThome 鐵人賽

DAY 8
3
Modern Web

真的好想離開 Vue 3 新手村 feat. CompositionAPI系列 第 8

真的好想離開 Vue 3 新手村 - Day 8: 認識 Vue directive 和 v-if v.s v-show

  • 分享至 

  • xImage
  •  

Vue Directive

什麼是 Vue directive?
簡單來說,就是在 Vue 模板中,我們常常用到的 v- 開頭的「指令」,像是:v-ifv-forv-bind 等等,都被稱作 directive,中文常看被翻成「指令」。

Vue 指令的使用語法視覺圖:

  • Name: 指令名稱
  • Argument: 部份指令需要接收參數,接在:之後
    • 可以使用動態參數,如::[動態參數],但值應為一般的字串或是 null (表示移除綁定)
    • 動態參數不接受單引號空白,這兩個字符本身就不是 HTML 接收的屬性名稱
  • Modifiers: 部份指令提供修飾符,可以利用修飾符調整指令操作
  • Value: 部份指令需要接收值,期待的值多數為 Javascript 表達式

指令的意義

Vue directive 設計的意義,就是能複用對 DOM 的簡單操作邏輯

Vue 已經內建好開發上常用的指令,快速的複習一遍:

  • v-text: 更新元素的 textContent
  • v-html: 更新元素的 innerHTML,注意 Vue 不會編譯這份 HTML,所以無法在裡面使用 vue 指令,也不會套用 scoped CSS
  • v-show: 根據綁定條件(truthy / falsy)切換元素的 inline CSS
  • v-ifv-else-ifv-else: 根據綁定條件(truthy / falsy)決定是否渲染或銷毀該元素
  • v-for: 根據綁定的陣列、物件或數值渲染多個元素
  • v-on: 為元素綁定事件監聽,可以縮寫為 @
  • v-bind: 為元素動態綁定一個或多個屬性,可以縮寫為 :
  • v-model: 為<input><select><textarea> 或元件做值與輸入的雙向綁定
  • v-slot: 參數為 slot 名稱,能在 <template> 內放入對應的 slot 內容
  • v-pre: 不要「編譯」這個元素和他的後代,直接渲染即可(可以用來呈現 {{ }}
  • v-once: 只渲染元素一次,未來不需要再更新
  • v-cloak: 在沒有事前編譯打包的情況下,用來隱藏尚未編譯完成的模板(by CSS {display: none}),直接編譯完成再切換成顯示
  • v-memo: 可以給一個固定長度的陣列,只在陣列內的項目 value 改變時,更新元素或元件,如果陣列內的項目都不變,會繼續使用之前記住的 sub-tree(舉例:v-memo="[valueA, valueB],在 valueA 或 valueB 改變時更新,而 v-memo=[]v-once 效果一樣 )

以上是 Vue 提供的內建指令,讓大家可以一次瀏覽有什麼樣的指令可以用,用法可以參照官方文件這篇,後續會再針對幾個常用指令做更深入了解他們的用法和限制,例如:v-forv-bindv-onv-slot

今天先來認識條件式渲染v-if 系列和 v-show

註:Vue 提供開發者自訂指令,所以在看 UI framework 的時候,除了 Vue Component,有的也會提供 Vue Directive。


條件式渲染

1. v-ifv-else-ifv-else

三個指令可以搭配使用,如同 javascript 的 if-else 邏輯判斷,可以針對不同條件設定,控制顯示(渲染)對應的元素:

如果使用這三個 v-指令,使用這三個指令的元素要相連。

  • v-if 可以單獨使用
  • v-else-if 渲染元素要緊接在 v-ifv-else-if 後面
  • v-else 渲染元素要緊接在 v-ifv-else-if 後面

沒有按照這個規則的話, Vue 會報警告,( Vue 的警告訊息都很清楚)。
:::warning
Template compilation error: v-else/v-else-if has no adjacent v-if or v-else-if.
:::

但如果 v-else 在最後重複的話,Vue 不會報錯,會渲染最後一個 v-else 區塊。

一次隱藏/顯示多著元素

想要一次控制多個元素顯示的話,可以搭配 v-if<template> 製造一個 invisible wrapper,最後瀏覽器渲染時,不會有 <template>這層 wrapper,只有裡面的元素會被渲染上去。

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

2. v-show

會根據接收到的值,透過 CSS 控制元素的顯示(display: none)。
觀察 DOM 會發現,該元素無論初始值/接收到的值為 truefalse,都會出現在 DOM 上,只是顯示與否的差別。

  • 判斷為 true 時: 會 display
  • 判斷為 false 時: 會 display: none

小結

兩者的主要差別在於會不會重新渲染

v-if(組合包)

  • 只有在符合條件的時候會渲染到 DOM 上
  • 切換的效能成本較高
  • 顯示條件不常切換的元素可使用 v-if

v-show

  • 一開始就會在 DOM 上,即使一開始的 v-show 條件為 false,只有 CSS display 的差別(不論顯現與否,元件內容都可以從開發者工具看到)
  • 初始渲染的成本較高
  • 顯示條件經常切換,需要頻繁 toggle 的元素可使用 v-show

學習心得與延伸
一開始在練習語法上,對於兩者的差異感受不深。
後來知道,每次元件渲染都會經歷建立、掛載、(更新)、移除銷毀的過程,這就是所謂的「生命週期」,而昨天提到的 setup() 就是生命週期中,第一個被呼叫的 Hook。

  • v-show:不會重新渲染 > 表示 setup()<setup script>內程式碼只執行一次
  • v-if:會重新渲染 > 表示 setup()<setup script>內程式碼會在每次渲染都執行

如果今天在 setup script 內執行 side effect,例如:發 API,那透過 v-show 顯示的元件,只會在第一次掛載時執行發 API 的動作;透過 v-if 渲染的元件,則是每次渲染都會發一次 API。

總結

  1. Vue Directive:
    • template 中常用的 v- 開頭特殊屬性,稱為 Vue Directive(指令)
    • 用來複用對 DOM 的簡單操作邏輯
    • 可以自訂指令,參考文件
  2. 條件式渲染:
    • v-ifv-else-ifv-else
      • v-else-if 渲染元素要緊接在 v-ifv-else-if 後面
      • v-else 渲染元素要緊接在 v-ifv-else-if 後面
      • 會根據條件渲染或銷毀元素
      • 切換的效能成本較高,適合條件不常切換的元素
    • v-show
      • 一開始就會在 DOM 上,即使初始條件為 false
      • 會根據條件控制元素 CSS 樣式(display: none)
      • 初始渲染的成本較高,適合條件經常切換的元素

參考資料


上一篇
真的好想離開 Vue 3 新手村 - Day 7: 深入了解 <script setup> 語法糖
下一篇
真的好想離開 Vue 3 新手村 - Day 9: v-for 與他的坑 feat. key & v-if
系列文
真的好想離開 Vue 3 新手村 feat. CompositionAPI31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

1
Chris
iT邦新手 3 級 ‧ 2022-11-09 15:15:55

v-clock 拼錯字!是 v-cloak 參考

安揪拉 iT邦新手 4 級 ‧ 2022-11-09 19:42:10 檢舉

天阿,已更正,謝謝揪錯 ><

1
Chris
iT邦新手 3 級 ‧ 2022-11-09 15:28:38

v-memo : 「誰」改變了,才更新這個 DOM。
(滿足條件 (某一個變數更新的話) 就可以再次 v-once)

v-memo="[]" == v-once

<tag v-memo="[誰]"></tag>

我要留言

立即登入留言